package com.lvfuyang.commonproject.interceptor;

import com.lvfuyang.commonproject.util.JwtUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

/**
 * JWT验证拦截器，jwt默认在请求头的 Authorization 中
 * 浏览器默认会先发送options请求看是否允许跨域请求，这里需要允许
 *     允许通过的域名在：allowedOrigins 中
 * 在这里不检测手机端jwt鉴权，可以详见 isMobileRequest 方法，也可以手动取消
 */
@Slf4j
@Component
public class JwtVerify implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 获取请求路径和方法
        String requestURI = request.getRequestURI();
        String method = request.getMethod();
        log.info("拦截请求: {} {}", method, requestURI);

        // 如果是OPTIONS预检请求，检查Origin是否允许
        if ("OPTIONS".equals(method)) {
            String origin = request.getHeader("Origin");
            log.info("OPTIONS请求 - URI: {}, Origin: {}", requestURI, origin);

            // 检查Origin是否在允许列表中
            /*
                浏览器默认会先发送options请求看是否允许跨域请求，这里需要允许
             */
            if (isAllowedOrigin(origin)) {
                log.info("允许的OPTIONS请求，放行: Origin={}, URI={}", origin, requestURI);
                return true;
            } else {
                log.warn("不允许的OPTIONS请求: Origin={}, URI={}", origin, requestURI);
                response.setStatus(HttpServletResponse.SC_FORBIDDEN);
                response.setContentType("application/json;charset=UTF-8");
                response.getWriter().write("{\"code\":403,\"message\":\"不允许的来源域名\"}");
                return false;
            }
        }

        // 检查是否为手机端请求，如果是则跳过JWT验证
        if (isMobileRequest(request)) {
            log.info("检测到手机端请求，跳过JWT验证: {} {}", method, requestURI);
            return true;
        }

        // 获取Authorization头（尝试两种大小写格式）
        String authorization = request.getHeader("Authorization");
        if (!StringUtils.hasText(authorization)) {
            authorization = request.getHeader("authorization");
        }

        log.info("获取到的Authorization头: {}", authorization);

        // 如果没有Authorization头，返回401
        if (!StringUtils.hasText(authorization)) {
            log.warn("请求未携带Authorization头: {} {}", method, requestURI);
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write("{\"code\":401,\"message\":\"未授权访问\"}");
            return false;
        }

        // 验证Authorization格式
        if (!authorization.startsWith("Bearer ")) {
            log.warn("Authorization格式错误: {}", authorization);
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write("{\"code\":401,\"message\":\"无效的认证信息\"}");
            return false;
        }

        // 提取token
        String token = authorization.replace("Bearer ", "");

        try {
            // 验证token
            if (!JwtUtil.validateToken(token)) {
                log.warn("Token已过期或无效: {}", token);
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                response.setContentType("application/json;charset=UTF-8");
                response.getWriter().write("{\"code\":401,\"message\":\"Token已过期或无效\"}");
                return false;
            }

            // 验证token中的用户信息
            String userId = JwtUtil.getUserIdFromToken(token);
            String username = JwtUtil.getUsernameFromToken(token);

            if (!StringUtils.hasText(userId) || !StringUtils.hasText(username)) {
                log.warn("Token中缺少用户信息: {}", token);
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                response.setContentType("application/json;charset=UTF-8");
                response.getWriter().write("{\"code\":401,\"message\":\"无效的用户信息\"}");
                return false;
            }

            // 将用户信息存入请求属性中，供后续使用
            request.setAttribute("userId", userId);
            request.setAttribute("username", username);
            request.setAttribute("isMobile", false);

            log.info("Token验证通过: userId={}, username={}", userId, username);
            return true;

        } catch (Exception e) {
            log.error("Token验证过程发生错误", e);
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write("{\"code\":401,\"message\":\"Token验证失败\"}");
            return false;
        }
    }

    /**
     * 检查是否为手机端请求
     * 根据多个条件判断：User-Agent、客户端类型头、请求路径等
     */
    private boolean isMobileRequest(HttpServletRequest request) {
        // 1. 检查自定义客户端类型头
        String clientType = request.getHeader("X-Client-Type");
        if ("mobile".equalsIgnoreCase(clientType) || "app".equalsIgnoreCase(clientType)) {
            log.info("通过X-Client-Type头识别为手机端: {}", clientType);
            return true;
        }

        // 2. 检查请求路径是否包含移动端标识
        String requestURI = request.getRequestURI();
        if (requestURI.contains("/mobile/") || requestURI.contains("/app/") || requestURI.contains("/m/")) {
            log.info("通过请求路径识别为手机端: {}", requestURI);
            return true;
        }

        // 3. 检查User-Agent是否包含移动设备标识
        String userAgent = request.getHeader("User-Agent");
        if (StringUtils.hasText(userAgent)) {
            String lowerUserAgent = userAgent.toLowerCase();
            // 常见的移动设备User-Agent关键词
            String[] mobileKeywords = {
                    "android", "iphone", "ipad", "ipod", "blackberry",
                    "windows phone", "mobile", "webos", "opera mini",
                    "dart-io", "flutter"  // Flutter应用的User-Agent标识
            };

            for (String keyword : mobileKeywords) {
                if (lowerUserAgent.contains(keyword)) {
                    log.info("通过User-Agent识别为手机端: {}", userAgent);
                    return true;
                }
            }
        }

        // 4. 检查特定的移动端API接口路径模式
        // 如果有专门的移动端API路径模式，可以在这里添加
        if (requestURI.matches(".*/(inspect|location|device)/.*")) {
            // 可以根据具体的移动端API路径模式来判断
            // 这里暂时注释掉，避免误判
            // log.info("通过API路径模式识别为可能的手机端请求: {}", requestURI);
            // return true;
        }

        return false;
    }

    /**
     * 验证Origin是否在允许列表中（与WebConfig保持一致）
     */
    private boolean isAllowedOrigin(String origin) {
        if (!StringUtils.hasText(origin)) {
            return false;
        }

        // 定义允许的Origin列表（与WebConfig中的配置保持一致）
        String[] allowedOrigins = {
                "http://localhost:5173",
                "http://tyfxg.daqiaobugong.cn:50613"
        };

        for (String allowedOrigin : allowedOrigins) {
            if (allowedOrigin.equals(origin)) {
                return true;
            }
        }

        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 请求处理完成后的操作
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 请求完成后的清理操作
    }
}
